package bgapi

import (
	"bgs/db"
	sqlc "bgs/db/sqlc"
	activityService "bgs/service/activity"
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"github.com/nsqio/go-nsq"
	"go.uber.org/zap"
)

var (
	lastActivityUserPvLogMessage *ActivityUserPvLogMessage = nil
)

// ActivityUserPvLogMessage ActivityUserPvLog message struct
type ActivityUserPvLogMessage struct {
	TS   int64 `json:"ts"`
	Data struct {
		// 冗余查询用
		ActivityID int64 `json:"activity_id"`
		// 用户
		UserID int64 `json:"user_id"`
		// 分享用户
		ShareUserID int64  `json:"share_user_id"`
		Page        string `json:"page"`
	} `json:"data"`
}

// ActivityUserPvLogHandler ActivityUserPvLog message handler
type ActivityUserPvLogHandler struct {
	dao             *db.PgDao
	slog            *zap.SugaredLogger
	activityService *activityService.ActivityServiceImp
}

// NewActivityUserPvLogHandler create a new handler for ActivityUserPvLog
func NewActivityUserPvLogHandler(
	pgdao *db.PgDao,
	slog *zap.SugaredLogger,
	activityService *activityService.ActivityServiceImp,
) *ActivityUserPvLogHandler {
	return &ActivityUserPvLogHandler{
		dao:             pgdao,
		slog:            slog.With("module", "ActivityUserPvLogHandler"),
		activityService: activityService,
	}
}

// HandleMessage implements the Handler interface.
func (h *ActivityUserPvLogHandler) HandleMessage(m *nsq.Message) error {
	if len(m.Body) == 0 {
		// Returning nil will automatically send a FIN command to NSQ to mark the message as processed.
		return nil
	}

	h.slog.Infof("message=>%s", string(m.Body))

	v := &ActivityUserPvLogMessage{}
	if decodeErr := json.NewDecoder(bytes.NewReader(m.Body)).Decode(v); decodeErr != nil {
		return fmt.Errorf("无法解析信息[ActivityUserPvLogMessage]: %v", decodeErr)
	}
	if lastActivityUserPvLogMessage != nil && lastActivityUserPvLogMessage.TS >= v.TS {
		h.slog.Infof("过时的消息: lastActivityUserPvLogMessage.TS:%v,v.TS:%v", lastActivityUserPvLogMessage.TS, v.TS)
		return nil
	}
	ctx := context.Background()

	err := h.dao.NewTxRunner().SqlcExecTx(ctx, func(q *sqlc.Queries) (err error) {
		activityID := v.Data.ActivityID
		_, err = q.CreateActivityUserPvLog(ctx, sqlc.CreateActivityUserPvLogParams{
			ActivityID:  activityID,
			UserID:      v.Data.UserID,
			ShareUserID: sqlc.NInt64FromInt64(v.Data.ShareUserID),
			Page:        v.Data.Page,
		})
		if err != nil {
			return
		}
		activity, err := q.GetActivity(ctx, activityID)
		if err != nil {
			return
		}
		err = h.activityService.UpdateActivityExposureStatSinceAccessedByC(ctx, q, &activity)
		if err != nil {
			return
		}
		return
	})

	if err != nil {
		return err
	}

	lastActivityUserPvLogMessage = v
	// Returning a non-nil error will automatically send a REQ command to NSQ to re-queue the message.
	return nil
}
